const express = require("express");
const app = express();
const bodyParser = require("body-parser");
//token解析中间件 一定要在路由之前配置解析 Token 的中间件
const expressJWT = require("express-jwt");
const expressWs = require("express-ws");
expressWs(app);

const jwt = require("jsonwebtoken");

// 使用cors中间件解决跨域问题
const cors = require("cors");
//映入解密
const config = require("./config");

const userRouter = require("./api/user.js");

const udRouter = require("./api/upDownLoad.js");

const { wsRouter } = require("./api/ws.js");

const chatUserRouter = require("./api/chatUser.js");
const pool = require("./pool.js");

// 静态托管
app.use(express.static("public"));

app.use(wsRouter);

app.use(cors());

// parse application/x-www-form-urlencoded  使用中间件将post传递参数转为对象
app.use(bodyParser.urlencoded({ extended: false }));

// parse application/json
app.use(bodyParser.json());

// 注册全局中间件  链式调用 unless 方法，接收一个配置对象，path 字段设置一个正则表达式，表示不需要 token 身份认证的路由前缀。
app.use(
  expressJWT({
    // 加密时设置的密钥
    secret: config.jwtSecretKey,
    // 设置算法
    algorithms: ["HS256"],
    // 无token请求不进行解析，并且抛出异常
    // credentialsRequired: false
  }).unless({
    path: [
      "/user/register",
      "/user/login",
      "/chatUser/register",
      "/chatUser/login",
      {
        url: /^\/public\/.*/,
        methods: ["GET", "POST"],
      },
    ],
  })
);

// 全局拦截器  验证token是否有效
app.use((req, res, next) => {
  if (!req.headers.authorization) {
    next();
    return;
  }
  const token = req.headers.authorization.split(" ")[1];
  jwt.verify(token, config.jwtSecretKey, (err, decoded) => {
    if (err) {
      throw err;
    }
    pool.query(
      "SELECT * FROM chat_user_token WHERE user_name = ?",
      [decoded.user_name],
      (err, result) => {
        if (err) {
          throw err;
        }
        let tokenIsTimeout = token !== result[0].user_token;
        if (tokenIsTimeout) {
          res.send({
            status: 402,
            data: {},
            message: "账号已在其他地方登录，请确定账号安全！",
          });
        } else {
          next();
        }
      }
    );
  });
});

// 错误中间件 当token失效时 返回信息
app.use((err, req, res, next) => {
  console.log(err);
  if (err.name === "UnauthorizedError") {
    res.send({
      status: 401,
      data: {},
      message: "登录信息失效，请重新登录！",
    });
  }
});

app.use("/user", userRouter);

app.use("/ud", udRouter);

app.use("/chatUser", chatUserRouter);

app.listen(5000, () => {
  console.log("连接5000端口成功");
});
